home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Unsupported Tools / SignatureToApp 1.1 / SignatureToApp.c < prev    next >
Encoding:
Text File  |  1992-06-16  |  8.4 KB  |  317 lines  |  [TEXT/KAHL]

  1. ////
  2. ////    SignatureToApp.c        Implementation of the SignatureToApp function.
  3. ////
  4. ////    By Jens Alfke            ©1991 Apple Computer, Inc. All rights reserved.
  5. ////
  6.  
  7.  
  8. #include <Errors.h>
  9. #include <Files.h>
  10. #include <Processes.h>
  11. #include <Folders.h>
  12. #include <AppleEvents.h>
  13.  
  14. #include "SignatureToApp.h"
  15.  
  16.  
  17.    ////////////////////////////////////////////////////////////
  18.   //    FindRunningAppBySignature                            //
  19.  //            Search process list for app with this signature//
  20. ////////////////////////////////////////////////////////////
  21. static OSErr
  22. FindRunningAppBySignature( OSType sig, ProcessSerialNumber *psn, FSSpec *fileSpec )
  23. {
  24.     OSErr err;
  25.     ProcessInfoRec info;
  26.     
  27.     psn->highLongOfPSN = 0;
  28.     psn->lowLongOfPSN  = kNoProcess;
  29.     do{
  30.         err= GetNextProcess(psn);
  31.         if( !err ) {
  32.             info.processInfoLength = sizeof(info);
  33.             info.processName = NULL;
  34.             info.processAppSpec = fileSpec;
  35.             err= GetProcessInformation(psn,&info);
  36.         }
  37.     } while( !err && info.processSignature != sig );
  38.  
  39.     if( err )
  40.         fileSpec->name[0] = 0;                                // Clear name if not found
  41.     else
  42.         *psn = info.processNumber;
  43.     return err;
  44. }
  45.  
  46.  
  47.    ////////////////////////////////////////////////////////////
  48.   //    GetSysVolume                                        //
  49.  //            Get the vRefNum of the system (boot) volume       //
  50. ////////////////////////////////////////////////////////////
  51. static OSErr
  52. GetSysVolume( short *vRefNum )
  53. {
  54.     long dir;
  55.     
  56.     return FindFolder(kOnSystemDisk,kSystemFolderType,false, vRefNum,&dir);
  57. }
  58.  
  59.  
  60.    ////////////////////////////////////////////////////////////
  61.   //    GetIndVolume                                        //
  62.  //            Get the vRefNum of an indexed on-line volume   //
  63. ////////////////////////////////////////////////////////////
  64. static OSErr
  65. GetIndVolume( short index, short *vRefNum )
  66. {
  67.     ParamBlockRec pb;
  68.     OSErr err;
  69.     
  70.     pb.volumeParam.ioCompletion = NULL;
  71.     pb.volumeParam.ioNamePtr = NULL;
  72.     pb.volumeParam.ioVolIndex = index;
  73.     
  74.     err= PBGetVInfo(&pb,false);
  75.     
  76.     *vRefNum = pb.volumeParam.ioVRefNum;
  77.     return err;
  78. }
  79.  
  80.  
  81.    ////////////////////////////////////////////////////////////
  82.   //    VolHasDesktopDB                                        //
  83.  //            Check if a volume supports desktop DB calls       //
  84. ////////////////////////////////////////////////////////////
  85. static OSErr
  86. VolHasDesktopDB( short vRefNum, Boolean *hasDesktop )
  87. {
  88.     typedef struct {                        // Volume Info Rec; see IM-VI 25-32
  89.         short    vMVersion;
  90.         long    vMAttrib;
  91.         Handle    vMLocalHand;
  92.         long    vMServerAddr;
  93.         long    vMVolumeGrade;
  94.         short    vMForeignPrivID;
  95.     } VolInfoRec;
  96.     const bHasNewDesk = 1L <<12;            // Flag mask for vMAttrib field
  97.     
  98.     HParamBlockRec pb;
  99.     VolInfoRec info;
  100.     OSErr err;
  101.     
  102.     long i, *ip;
  103.     for( i=0, ip=(long*)&pb; i<sizeof(pb)/sizeof(long); i++ )        // Clear pb
  104.         *ip++ = 0;
  105.     pb.ioParam.ioCompletion = NULL;
  106.     pb.ioParam.ioNamePtr = NULL;
  107.     pb.ioParam.ioVRefNum = vRefNum;
  108.     pb.ioParam.ioBuffer = (Ptr)&info;
  109.     pb.ioParam.ioReqCount = sizeof(VolInfoRec);
  110.     
  111.     err= PBHGetVolParms(&pb,false);            // Get volume info
  112.  
  113.     *hasDesktop = err==noErr && (info.vMAttrib & bHasNewDesk)!=0;
  114.     return err;
  115. }
  116.  
  117.  
  118.    ////////////////////////////////////////////////////////////
  119.   //    FindAppOnVolume                                        //
  120.  //            Ask vol's desktop db for application           //
  121. ////////////////////////////////////////////////////////////
  122. static OSErr
  123. FindAppOnVolume( OSType sig, short vRefNum, FSSpec *file )
  124. {
  125.     DTPBRec pb;
  126.     OSErr err;
  127.     short refNum;
  128.     
  129.     long i, *ip;
  130.     for( i=0, ip=(long*)&pb; i<sizeof(pb)/sizeof(long); i++ )        // Clear pb
  131.         *ip++ = 0;
  132.  
  133.     pb.ioCompletion = NULL;
  134.     pb.ioVRefNum = vRefNum;
  135.     pb.ioNamePtr = NULL;
  136.     err= PBDTGetPath(&pb);                // Puts DT refnum into pb.ioDTRefNum
  137.     if( err ) return err;
  138.     refNum = pb.ioDTRefNum;
  139.     
  140.     pb.ioCompletion = NULL;
  141.     pb.ioDTRefNum = refNum;
  142.     pb.ioIndex = 0;
  143.     pb.ioFileCreator = sig;
  144.     pb.ioNamePtr = (StringPtr)&file->name;
  145.     err= PBDTGetAPPLSync(&pb);                        // Find it!
  146.     
  147.     if( err == fnfErr )
  148.         err = afpItemNotFound;                        // Bug in PBDTGetAPPL
  149.     if( err )
  150.         return err;                                    // Returns afpItemNotFound if app wasn't found.
  151.  
  152.     file->vRefNum = vRefNum;
  153.     file->parID = pb.ioAPPLParID;
  154.     return noErr;
  155. }
  156.  
  157.  
  158.    ////////////////////////////////////////////////////////////
  159.   //    BuildODoc                                            //
  160.  //            Construct an 'odoc' Apple event                   //
  161. ////////////////////////////////////////////////////////////
  162. static OSErr
  163. BuildODoc( const FSSpec *fileSpec, OSType signature, const ProcessSerialNumber *psn,
  164.            AppleEvent *event )
  165. {
  166.     // If psn is non-NULL the event will be addressed to that process;
  167.     // otherwise it'll be addressed to the supplied signature.
  168.     
  169.     AEDesc addr,ev;
  170.     OSErr err;
  171.     
  172.     event->descriptorType = 0;
  173.     event->dataHandle = NULL;
  174.     
  175.     if( psn )
  176.         err= AECreateDesc(typeProcessSerialNumber,(void*)psn,sizeof(*psn), &addr);
  177.     else
  178.         err= AECreateDesc(typeApplSignature,(void*)&signature,sizeof(signature), &addr);
  179.     if( err ) return err;
  180.     
  181.     err= AECreateAppleEvent(kCoreEventClass,kAEOpenDocuments, &addr,kAutoGenerateReturnID,0,&ev);
  182.     AEDisposeDesc(&addr);
  183.     if( !err )
  184.         err= AEPutParamPtr(&ev,keyDirectObject, typeFSS,(void*)fileSpec,sizeof(FSSpec));
  185.     
  186.     if( err )
  187.         AEDisposeDesc(&ev);
  188.     else
  189.         *event = ev;
  190.     return err;
  191. }
  192.  
  193.  
  194.    ////////////////////////////////////////////////////////////
  195.   //    LaunchIt                                            //
  196.  //            Launch app once we have a location               //
  197. ////////////////////////////////////////////////////////////
  198. static OSErr
  199. LaunchIt( const FSSpec *fileSpec, LaunchFlags launchControlFlags, const AppleEvent *odoc,
  200.             ProcessSerialNumber *psn )
  201. {
  202.     LaunchParamBlockRec pb;
  203.     AEDesc paramDesc;
  204.     OSErr err;
  205.     
  206.     pb.launchBlockID = extendedBlock;
  207.     pb.launchEPBLength = extendedBlockLen;
  208.     pb.launchFileFlags = launchNoFileFlags;
  209.     pb.launchControlFlags = launchControlFlags | launchNoFileFlags;
  210.     pb.launchAppSpec = (FSSpec*)fileSpec;
  211.     
  212.     if( odoc ) {
  213.         err= AECoerceDesc(odoc,typeAppParameters, ¶mDesc);
  214.         if( err ) return err;
  215.         HLock(paramDesc.dataHandle);
  216.         pb.launchAppParameters = (void*) *paramDesc.dataHandle;
  217.     } else
  218.         pb.launchAppParameters = NULL;
  219.     
  220.     err= LaunchApplication(&pb);
  221.     
  222.     if( odoc )
  223.         AEDisposeDesc(¶mDesc);
  224.         
  225.     if( !err )
  226.         *psn = pb.launchProcessSN;
  227.     return err;
  228. }
  229.  
  230.  
  231.    ////////////////////////////////////////////////////////////
  232.   //    SignatureToApp                                        //
  233.  //            Main routine. Find app, launching if need be   //
  234. ////////////////////////////////////////////////////////////
  235. OSErr
  236. SignatureToApp( OSType sig, const FSSpec *document,
  237.                 ProcessSerialNumber *psn, FSSpec *fileSpec, Boolean *launched,
  238.                 Sig2App_Mode mode,
  239.                 LaunchFlags launchControlFlags )
  240. {
  241.     ProcessSerialNumber dummyPSN;
  242.     OSErr err;
  243.     short sysVRefNum, vRefNum, index;
  244.     FSSpec file;
  245.     Boolean hasDesktopDB;
  246.     
  247.     if( launched )
  248.         *launched = false;
  249.     if( psn == NULL )
  250.         psn = &dummyPSN;                                // Allow psn parameter to be NIL
  251.     
  252.     // First see if it's already running:
  253.     
  254.     err= FindRunningAppBySignature(sig,psn,fileSpec);
  255.     
  256.     if( err==noErr && mode==Sig2App_LaunchApplication ) {
  257.         if( (launchControlFlags & launchDontSwitch) == 0 ) {
  258.             err= SetFrontProcess(psn);                // They wanted to switch to it…
  259.             if( err ) return err;
  260.         }
  261.         if( document ) {
  262.             // They wanna open a document, so do it:
  263.             AppleEvent aevt;
  264.             err= BuildODoc(document,sig,psn, &aevt);
  265.             if( !err )
  266.                 err= AESend(&aevt,NULL,kAENoReply | kAEAlwaysInteract,
  267.                             kAENormalPriority,kAEDefaultTimeout,
  268.                             NULL,NULL);
  269.             AEDisposeDesc(&aevt);
  270.         }
  271.         return err;
  272.     }
  273.  
  274.     if( err != procNotFound || mode<=Sig2App_FindProcess )
  275.         return err;
  276.     
  277.     // Well, it's not running but it's okay to launch it. Let's have a look around:
  278.     
  279.     if( err= GetSysVolume(&sysVRefNum) ) return err;    // Find boot volume
  280.     vRefNum = sysVRefNum;                                // Start search with boot volume
  281.     index = 0;
  282.     do{
  283.         if( index==0 || vRefNum != sysVRefNum ) {
  284.             if( err= VolHasDesktopDB(vRefNum,&hasDesktopDB) )
  285.                 return err;
  286.             if( hasDesktopDB ) {                        // If volume has a desktop DB,
  287.                 err= FindAppOnVolume(sig,vRefNum, &file);        // ask it to find app
  288.                 if( err==noErr ) {
  289.                     // FOUND IT!
  290.                     if( fileSpec )
  291.                         *fileSpec = file;
  292.                     if( mode==Sig2App_LaunchApplication ) {
  293.                         AEDesc odoc;
  294.                         if( document )
  295.                             err= BuildODoc(document,sig,NULL,&odoc);
  296.                         if( err ) return err;
  297.                         err= LaunchIt(&file,launchControlFlags,        // Launch it!
  298.                                         document ?&odoc :NULL,
  299.                                         psn);
  300.                         if( document )
  301.                             AEDisposeDesc(&odoc);
  302.                         if( !err && launched )
  303.                             *launched = true;
  304.                     }
  305.                     return err;
  306.                     
  307.                 } else if( err != afpItemNotFound )
  308.                     return err;
  309.             }
  310.         }
  311.         err= GetIndVolume(++index,&vRefNum);                // Else go to next volume
  312.     } while( err==noErr );                                // Keep going until we run out of vols
  313.     
  314.     if( err==nsvErr || err==afpItemNotFound )
  315.         err= fnfErr;                                    // File not found on any volume
  316.     return err;
  317. }